#ifndef EVENTLOOP_IOCHANNELPROXY
#define EVENTLOOP_IOCHANNELPROXY

#include "utility/Noncopyable.h"
#include "utility/chrono.h"
#include "utility/func.h"

#include <memory>
#include <optional>
#include <string>


class EventloopProxy;
class IOchannel;

class IOchannelProxy final
{
public:
    IOchannelProxy(IOchannel &channel, const EventloopProxy &eventloopProxy):
        _closeCallback{default_func},
        _errorCallback{default_func},
        _readCallback{default_timepoint_func},
        _writeCallback{default_func},
        _channel{channel},
        _eventloopProxy{eventloopProxy},
        _tie{},
        _listenEvents{0},
        _returnEvents{0},
        _handlingEvent{false} {}
    ~IOchannelProxy();

    int fd() const;
    const EventloopProxy &eventloopProxy() const { return _eventloopProxy; }
    int listen_events() const { return _listenEvents; }
    std::string listen_events_string() const;
    const std::string &name() const;
    int return_events() const { return _returnEvents; }
    std::string return_events_string() const;

    void set_close_callback(const TrivialFunc &callback) {
        _closeCallback = callback;
    }
    void set_error_callback(const TrivialFunc &callback) {
        _errorCallback = callback;
    }
    void set_read_callback(const TimepointFunc &callback) {
        _readCallback = callback;
    }
    void set_write_callback(const TrivialFunc &callback) {
        _writeCallback = callback;
    }
    void set_return_events(int events) { _returnEvents = events; }

    void disable();
    void disable_reading();
    void disable_writing();
    void enable_reading();
    void enable_writing();
    bool is_idling() const;
    bool is_reading() const;
    bool is_writing() const;

    void handle_event(Utility::timepoint t);
    void tie(const std::shared_ptr<void> &obj) { _tie = obj; }

private:
    NONCOPYABLE(IOchannelProxy);

    void _close_event_handler() const;
    void _error_event_handler() const;
    void _event_handler(Utility::timepoint t);
    void _read_event_handler(Utility::timepoint t) const;
    void _write_event_handler() const; 

    TrivialFunc _closeCallback;
    TrivialFunc _errorCallback;
    TimepointFunc _readCallback;
    TrivialFunc _writeCallback;
    IOchannel &_channel;
    const EventloopProxy &_eventloopProxy;
    std::optional<std::weak_ptr<void>> _tie;
    int _listenEvents;
    int _returnEvents;
    bool _handlingEvent;
};

inline bool operator==(const IOchannelProxy &lhs, const IOchannelProxy &rhs) {
    return &lhs == &rhs;
}



#endif